//
// Created by Win on 2015/11/30.
//

#include <stdio.h>
#include <iconv2utf8.h>

#include "corba_comm.h"
#include "frcomm.h"
#include "frbyte_buffer.h"
#include "frreport_comm.h"
#include "weblogic_parse.h"
#include "was_ejb.h"

int giop_reply_v2(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_corba_private *p_st_private);


/*!
 * corba giop header 解析
 *
 * \p_st_data                    (输入数据)
 * \p_st_body_data               (数据上报链表)
 * \p_st_private                 (私有数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 */
int corba_giop_header_parse(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_corba_private *p_st_private)
{
    int i_ret = 0;
    char arr_server[9];
    short s_version_major = 0, s_version_minor = 0;
    int is_little_endian = 0;

    if(p_st_data == NULL || p_st_body_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    //MAGIC  GIOP
    i_ret = bytebuff_get_bytes(p_st_data, arr_server, 4);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_get_short(p_st_data, 1, (uint16_t *)&s_version_major, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_get_short(p_st_data, 1, (uint16_t *)&s_version_minor, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    p_st_private->i_version = s_version_minor;

    //GIOP 1.0
    snprintf(arr_server + 4, 5, " %d.%d", s_version_major, s_version_minor);
    if(p_st_private->p_server)
        frfree(p_st_private->p_server);
    p_st_private->p_server = frstrdup(arr_server);

    //little endian
    i_ret = bytebuff_get_int(p_st_data, 1, (uint32_t *)&is_little_endian, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //MESSAGE TYPE
    i_ret = bytebuff_get_int (p_st_data, 1, (uint32_t *)&p_st_private->i_message_type, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //message size
    if(is_little_endian & 0x1)
        p_st_private->i_endianess = BYTE_LITTLE_ENDIAN;
    else
        p_st_private->i_endianess = BYTE_BIG_ENDIAN;

    i_ret = bytebuff_get_int(p_st_data, 4, (uint32_t *)&p_st_private->i_data_len, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);

    return i_ret;

}

/*!
 * server context 解析
 *
 * \p_st_data                    (输入数据)
 * \p_st_body_data               (数据上报链表)
 * \p_st_private                 (私有数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 */
int corba_server_context_parse(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_corba_private *p_st_private)
{
    int i_ret = 0;
    int i_seq_len = 0;
    int i_skip_len = 0;

    if (p_st_data == NULL || p_st_body_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    i_ret = bytebuff_skip(p_st_data, 4);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_get_int(p_st_data, 4, (uint32_t *) &i_seq_len, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_skip(p_st_data, i_seq_len);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    if (p_st_data->ui_remaining)
    {
        i_skip_len = i_seq_len % 4;
        if (i_skip_len)
        {
            i_skip_len = 4 - i_skip_len;
        }

        i_ret = bytebuff_skip(p_st_data, i_skip_len);

        return i_ret;
    }

    return FR_SUCC;
}


/*!
 * server context list 解析
 *
 * \p_st_data                    (输入数据)
 * \p_st_body_data               (数据上报链表)
 * \p_st_private                 (私有数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 */
int corba_server_context_list_parse(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_corba_private *p_st_private)
{
    int i_ret = 0;
    int i_seq_len = 0;

    if(p_st_data == NULL || p_st_body_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    i_ret = bytebuff_get_int(p_st_data, 4, (uint32_t *)&i_seq_len, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //server context
    while (i_seq_len)
    {
        i_ret = corba_server_context_parse(p_st_data, p_st_body_data, p_st_private);
        if(i_ret == FR_FAIL)
            return FR_FAIL;

        i_seq_len--;
    }

    return FR_SUCC;
}

/*!
 * corba 获取 bytes
 *
 * \p_st_data                    (输入数据)
 * \p_st_private                 (私有数据)
 * \pp_out                       (字符串输出)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 */
int corba_get_bytes(Frbyte_Packet *p_st_data, L7session_corba_private *p_st_private, char **pp_out)
{
    int i_ret = 0;
    char *p_string = NULL;
    int i_str_len = 0;

    if(p_st_data == NULL || p_st_private == NULL || pp_out == NULL)
        return FR_FAIL;

    i_ret = bytebuff_get_int(p_st_data, 4, (uint32_t *)&i_str_len, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    p_string = (char *)frmalloc(i_str_len + 1);
    if(p_string == NULL)
        return FR_FAIL;

    i_ret = bytebuff_get_bytes(p_st_data, p_string, i_str_len);
    if(i_ret == FR_FAIL)
    {
        frfree(p_string);
        return FR_FAIL;
    }
    p_string[i_str_len] = '\0';

    *pp_out = p_string;
    return FR_SUCC;

}

/*!
 * corba 获取 字符串
 *
 * \p_st_data                    (输入数据)
 * \p_st_private                 (私有数据)
 * \pp_out                       (字符串输出)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 */
int corba_get_string(Frbyte_Packet *p_st_data, L7session_corba_private *p_st_private, char **pp_out)
{
    int i_ret = 0;
    char *p_string = NULL;
    int i_str_len = 0, i_skip_len = 0;

    if(p_st_data == NULL || p_st_private == NULL || pp_out == NULL)
        return FR_FAIL;

    i_ret = bytebuff_get_int(p_st_data, 4, (uint32_t *)&i_str_len, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    p_string = (char *)frmalloc(i_str_len);
    if(p_string == NULL)
        return FR_FAIL;

    i_ret = bytebuff_get_bytes(p_st_data, p_string, i_str_len);
    if(i_ret == FR_FAIL)
    {
        frfree(p_string);
        return FR_FAIL;
    }

    if(p_st_data->ui_remaining)
    {
        i_skip_len = i_str_len % 4;
        if(i_skip_len)
        {
            i_skip_len = 4 - i_skip_len;
            i_ret = bytebuff_skip(p_st_data, i_skip_len);
            if(i_ret == FR_FAIL)
            {
                frfree(p_string);
                return FR_FAIL;
            }
        }
    }

    *pp_out = p_string;
    return FR_SUCC;

}


/*!
 * corba 跳过字符串
 *
 * \p_st_data                    (输入数据)
 * \p_st_private                 (私有数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 */
int corba_skip_string(Frbyte_Packet *p_st_data, L7session_corba_private *p_st_private)
{
    int i_ret = 0;
    int i_str_len = 0, i_skip_len = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    i_ret = bytebuff_get_int(p_st_data, 4, (uint32_t *)&i_str_len, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_skip(p_st_data, i_str_len);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(p_st_data->ui_remaining)
    {
        i_skip_len = i_str_len % 4;
        if(i_skip_len)
        {
            i_skip_len = 4 - i_skip_len;
            i_ret = bytebuff_skip(p_st_data, i_skip_len);
            if(i_ret == FR_FAIL)
                return FR_FAIL;
        }
    }

    return i_ret;

}

void giop_set_alignment(Frbyte_Packet *p_st_data)
{
    while ( ( (bytebuff_length(p_st_data) - bytebuff_remaining(p_st_data)) % 8) != 0)
          bytebuff_skip(p_st_data, 1);
}

int giop_data_v0(Frbyte_Packet *p_st_data
                        , Frreport_body_data *p_st_body_data
                        , corba_session *p_st_session_private)
{
    L7session_corba_private *p_st_private = NULL;
    int i_ret = 0, i_request_principal_len = 0;
//    char *p_object_key = NULL;

    if(p_st_data == NULL || p_st_body_data == NULL
        || p_st_session_private == NULL || p_st_session_private->p_st_private == NULL)
        return FR_FAIL;

    p_st_private = p_st_session_private->p_st_private;

    //server context list
    i_ret = corba_server_context_list_parse(p_st_data, p_st_body_data, p_st_private);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //request id
    i_ret = bytebuff_get_int(p_st_data, 4, (uint32_t *)&p_st_private->i_request_id, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //response expected
    i_ret = bytebuff_get_int(p_st_data, 1, (uint32_t *)&p_st_private->i_response_required, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_skip(p_st_data, 3);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //object key
    i_ret = corba_skip_string(p_st_data, p_st_private);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //operation
    i_ret = corba_get_string(p_st_data, p_st_private, &p_st_private->p_title);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if (p_st_session_private->i_flag_weblogic)
    {
        p_st_session_private->p_wls_function = frstrdup(p_st_private->p_title);
        if (p_st_session_private->p_wls_function == NULL)
            return FR_FAIL;
    }

    if (p_st_session_private->is_was_ejb)
    {
        p_st_session_private->p_was_function = frstrdup(p_st_private->p_title);
        if (p_st_session_private->p_was_function == NULL)
            return FR_FAIL;
    }

    //giop.request_principal_len
    i_ret = bytebuff_get_int(p_st_data, 4, (uint32_t *)&i_request_principal_len, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_skip(p_st_data, i_request_principal_len);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}


int giop_data_v1(Frbyte_Packet *p_st_data
                        , Frreport_body_data *p_st_body_data
                        , corba_session *p_st_session_private)
{
    L7session_corba_private *p_st_private = NULL;
    int i_ret = 0, i_request_principal_len = 0;
//    char *p_object_key = NULL;

    if(p_st_data == NULL || p_st_body_data == NULL
        || p_st_session_private == NULL || p_st_session_private->p_st_private == NULL)
        return FR_FAIL;

    p_st_private = p_st_session_private->p_st_private;

    //server context list
    i_ret = corba_server_context_list_parse(p_st_data, p_st_body_data, p_st_private);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //request id
    i_ret = bytebuff_get_int(p_st_data, 4, (uint32_t *)&p_st_private->i_request_id, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //response expected
    i_ret = bytebuff_get_int(p_st_data, 1, (uint32_t *)&p_st_private->i_response_required, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //object key
    i_ret = corba_skip_string(p_st_data, p_st_private);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //operation
    i_ret = corba_get_string(p_st_data, p_st_private, &p_st_private->p_title);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if (p_st_session_private->i_flag_weblogic)
    {
        p_st_session_private->p_wls_function = frstrdup(p_st_private->p_title);
        if (p_st_session_private->p_wls_function == NULL)
            return FR_FAIL;
    }

    if (p_st_session_private->is_was_ejb)
    {
        p_st_session_private->p_was_function = frstrdup(p_st_private->p_title);
        if (p_st_session_private->p_was_function == NULL)
            return FR_FAIL;
    }

    //giop.request_principal_len
    i_ret = bytebuff_get_int(p_st_data, 1, (uint32_t *)&i_request_principal_len, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_skip(p_st_data, i_request_principal_len);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}

int giop_target_parse(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, corba_session *p_st_session_private)
{
    L7session_corba_private *p_st_private = NULL;
    char *p_key_address = NULL;
    int i_ret = 0, i_len = 0;
    short s_target = 0;
    int i_skip_len = 0;
    int i_pos = 0, i_found = 0;
    int i_key_addr_len = 0;

    if(p_st_data == NULL || p_st_body_data == NULL
        || p_st_session_private == NULL || p_st_session_private->p_st_private == NULL)
        return FR_FAIL;

    p_st_private = p_st_session_private->p_st_private;

    i_ret = bytebuff_get_short(p_st_data, 2, (uint16_t *)&s_target, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_skip(p_st_data, 2);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    switch (s_target)
    {
        case 0:
            //bytes
            i_ret = bytebuff_get_int(p_st_data, 4, (uint32_t *)&i_len, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
            if(i_ret == FR_FAIL)
                return FR_FAIL;

            i_key_addr_len = i_len;

            //CDR 编码对其
            i_skip_len = i_len % 4;
            if(i_skip_len)
            {
                i_skip_len = 4 - i_skip_len;
                i_len += i_skip_len;
            }

            i_pos = bytebuff_getPosition (p_st_data);

            // 判断weblogic
            i_ret = bytebuff_memstr(p_st_data, i_pos, i_pos + i_len, "weblogic", 8, &i_found);
            if(i_ret == FR_SUCC)
                p_st_session_private->i_flag_weblogic = 1;

            // 判断Websphere ejb
            i_ret = bytebuff_memstr(p_st_data, i_pos, i_pos + 4, "JMBI", 4, &i_found);
            if (i_ret == FR_SUCC)
            {
                p_st_session_private->is_was_ejb = 1;

                // Key Address保存
                p_key_address = (char *)frmalloc(i_key_addr_len + 1);
                if (p_key_address == NULL)
                    return FR_FAIL;

                if (bytebuff_get_bytes(p_st_data, p_key_address, i_key_addr_len) == FR_FAIL)
                {
                    frfree(p_key_address);
                    return FR_FAIL;
                }
                p_key_address[i_key_addr_len] = '\0';

                p_st_session_private->p_key_address = p_key_address;
                p_st_session_private->i_key_addr_len = i_key_addr_len;

                if (i_key_addr_len < i_len)
                {
                    i_ret = bytebuff_skip(p_st_data, i_len - i_key_addr_len);
                    if(i_ret == FR_FAIL)
                        return FR_FAIL;
                }
            }
            else
            {
                i_ret = bytebuff_skip(p_st_data, i_len);
                if(i_ret == FR_FAIL)
                    return FR_FAIL;
            }

            break;

        //TaggedProfile
        case 1:
            //tag  int
            i_ret = bytebuff_skip(p_st_data, 4);
            if(i_ret == FR_FAIL)
                return FR_FAIL;

            //bytes
            i_ret = bytebuff_get_int(p_st_data, 4, (uint32_t *)&i_len, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
            if(i_ret == FR_FAIL)
                return FR_FAIL;

            i_skip_len = i_len % 4;
            if(i_skip_len)
            {
                i_skip_len = 4 - i_skip_len;
                i_len += i_skip_len;
            }

            i_ret = bytebuff_skip(p_st_data, i_len);
            if(i_ret == FR_FAIL)
                return FR_FAIL;

            break;

        //IORAddressingInfo
        case 2:
            //profile_index  int
            i_ret = bytebuff_skip(p_st_data, 4);
            if(i_ret == FR_FAIL)
                return FR_FAIL;

            //type_id
            i_ret = corba_skip_string(p_st_data,p_st_private);
            if(i_ret == FR_FAIL)
                return FR_FAIL;

            //TaggedProfile
            //tag  int
            i_ret = bytebuff_skip(p_st_data, 4);
            if(i_ret == FR_FAIL)
                return FR_FAIL;

            //bytes
            i_ret = bytebuff_get_int(p_st_data, 4, (uint32_t *)&i_len, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
            if(i_ret == FR_FAIL)
                return FR_FAIL;

            //cdr 编码对其
            i_skip_len = i_len % 4;
            if(i_skip_len)
            {
                i_skip_len = 4 - i_skip_len;
                i_len += i_skip_len;
            }

            i_ret = bytebuff_skip(p_st_data, i_len);
            if(i_ret == FR_FAIL)
                return FR_FAIL;

            break;

        default:
            return FR_FAIL;
    }

    return FR_SUCC;
}

int giop_data_v2(Frbyte_Packet *p_st_data
                        , Frreport_body_data *p_st_body_data
                        , corba_session *p_st_session_private)
{
    L7session_corba_private *p_st_private = NULL;
    int i_ret = 0;

    if(p_st_data == NULL || p_st_body_data == NULL
        || p_st_session_private == NULL || p_st_session_private->p_st_private == NULL)
        return FR_FAIL;

    p_st_private = p_st_session_private->p_st_private;

    //request id
    i_ret = bytebuff_get_int(p_st_data, 4, (uint32_t *)&p_st_private->i_request_id, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //response flag   reserved
    i_ret = bytebuff_skip(p_st_data, 4);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //TARGET
    i_ret = giop_target_parse(p_st_data, p_st_body_data, p_st_session_private);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //operation
    i_ret = corba_get_string(p_st_data, p_st_private, &p_st_private->p_title);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if (p_st_session_private->i_flag_weblogic)
    {
        p_st_session_private->p_wls_function = frstrdup(p_st_private->p_title);
        if (p_st_session_private->p_wls_function == NULL)
            return FR_FAIL;
    }

    if (p_st_session_private->is_was_ejb)
    {
        p_st_session_private->p_was_function = frstrdup(p_st_private->p_title);
        if (p_st_session_private->p_was_function == NULL)
            return FR_FAIL;
    }

    //server context list
    i_ret = corba_server_context_list_parse(p_st_data, p_st_body_data, p_st_private);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) > 0)
        giop_set_alignment(p_st_data);

    return FR_SUCC;

}


/*
 * 0  1
 *
 */
int giop_reply_v0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_corba_private *p_st_private)
{
    int i_ret = 0;
    int i_request_id = 0;

    if(p_st_data == NULL || p_st_body_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    //context list
    i_ret = corba_server_context_list_parse(p_st_data, p_st_body_data, p_st_private);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_get_int(p_st_data, 4, (uint32_t *)&i_request_id, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if(i_ret == FR_FAIL || (i_request_id != p_st_private->i_request_id && p_st_private->i_request_id != 0))
        return FR_FAIL;

    //reply status
    i_ret = bytebuff_get_long(p_st_data, 4, (uint64_t *)&p_st_private->l_response_code, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}


int giop_reply_v2(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_corba_private *p_st_private)
{
    int i_ret = 0;
    int i_request_id = 0;

    if(p_st_data == NULL || p_st_body_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    //request id
    i_ret = bytebuff_get_int(p_st_data, 4, (uint32_t *)&i_request_id, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if(i_ret == FR_FAIL || (i_request_id != p_st_private->i_request_id && p_st_private->i_request_id != 0))
        return FR_FAIL;

    //reply status
    i_ret = bytebuff_get_long(p_st_data, 4, (uint64_t *)&p_st_private->l_response_code, (LITTLE_BIG_ENDIAN)p_st_private->i_endianess);
    if(i_ret == FR_FAIL)
        return FR_FAIL;
    //context list
    i_ret = corba_server_context_list_parse(p_st_data, p_st_body_data, p_st_private);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) > 0)
        giop_set_alignment(p_st_data);

    return FR_SUCC;

}


/*!
 * corba request 解析
 *
 * \p_st_data                    (输入数据)
 * \p_st_body_data               (数据上报链表)
 * \p_st_private                 (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC:成功\n
 *         APM_L7_ANALYZE_TODO:数据解析未结束\n
 *         APM_L7_ANALYZE_FAIL:失败\n
 */
int corba_request_parse(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, corba_session *p_st_session_private)
{
    int i_ret = 0;
    unsigned int ui_stub_len = 0, ui_stub_len_tmp = 0;
    char *p_stub_data = NULL;
    char *p_out = NULL;         //char set 转码
    L7session_corba_private *p_st_private = NULL;

    if(p_st_data == NULL || p_st_body_data == NULL
        || p_st_session_private == NULL || p_st_session_private->p_st_private == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = p_st_session_private->p_st_private;

    i_ret = corba_giop_header_parse(p_st_data, p_st_body_data, p_st_private);
    if(i_ret == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

    if((unsigned int)p_st_private->i_data_len > p_st_data->ui_remaining)
        return APM_L7_ANALYZE_TODO;

    switch (p_st_private->i_message_type)
    {
        case 0:
            switch (p_st_private->i_version)
            {
                case 0:
                    i_ret = giop_data_v0(p_st_data, p_st_body_data, p_st_session_private);
                    break;

                case 1:
                    i_ret = giop_data_v1(p_st_data, p_st_body_data, p_st_session_private);
                    break;

                case 2:
                    i_ret = giop_data_v2(p_st_data, p_st_body_data, p_st_session_private);
                    break;

                default:
                    return APM_L7_ANALYZE_FAIL;
            }

            if(i_ret == FR_FAIL)
                return APM_L7_ANALYZE_FAIL;

            break;

        case 1:
            switch (p_st_private->i_version)
            {
                case 0:
                case 1:
                    i_ret = giop_reply_v0(p_st_data, p_st_body_data, p_st_private);
                    if(i_ret == FR_FAIL)
                        return APM_L7_ANALYZE_FAIL;

                    break;

                case 2:
                    i_ret = giop_reply_v2(p_st_data, p_st_body_data, p_st_private);
                    if(i_ret == FR_FAIL)
                        return  APM_L7_ANALYZE_FAIL;

                    break;

                default:
                    return APM_L7_ANALYZE_FAIL;
            }

            if(i_ret == FR_FAIL)
                return APM_L7_ANALYZE_FAIL;

            break;


        default:
            if((unsigned int)p_st_private->i_data_len > p_st_data->ui_remaining)
                return APM_L7_ANALYZE_TODO;

            i_ret = bytebuff_skip (p_st_data, p_st_private->i_data_len);
            return i_ret == FR_SUCC ? APM_L7_ANALYZE_SUCC : APM_L7_ANALYZE_FAIL;
    }

    if (p_st_session_private->i_flag_weblogic)
    {
        i_ret = weblogic_stub_data_parse_req(p_st_session_private, p_st_data, p_st_body_data);
        if (i_ret == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
    }

    if (p_st_session_private->is_was_ejb)
    {
        i_ret = was_ejb_parse_req(p_st_session_private, p_st_body_data);
        if (i_ret == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
    }

    //STUB DATA
    if(p_st_data->ui_remaining)
    {
        //    p_stub_data
        p_stub_data = (char *)frmalloc(p_st_data->ui_remaining);
        if(p_stub_data == NULL)
            return APM_L7_ANALYZE_FAIL;

        ui_stub_len = p_st_data->ui_remaining;
        i_ret = bytebuff_get_bytes(p_st_data, p_stub_data, p_st_data->ui_remaining);
        if(i_ret == FR_FAIL)
        {
            frfree(p_stub_data);
            return APM_L7_ANALYZE_FAIL;
        }

        frreport_body_l7_add_int(p_st_body_data, "request.rpc.arg.size", 1);

        //GBK--> UTF8
        i_ret = iconv_to_utf8(p_stub_data, ui_stub_len, "gb18030", &p_out, &ui_stub_len_tmp);
        if(i_ret != 0)
        {
            if(p_out)
                frfree(p_out);
        }
        else
        {
            frfree(p_stub_data);
            p_stub_data = p_out;
            ui_stub_len = ui_stub_len_tmp;
        }

        i_ret = frreport_body_l7_add_bin(p_st_body_data, "request.rpc.arg.1", p_stub_data, ui_stub_len);
        frfree(p_stub_data);
        if(i_ret == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
    }

    return APM_L7_ANALYZE_SUCC;

}



/*!
 * corba response 解析
 *
 * \p_st_data                    (输入数据)
 * \p_st_body_data               (数据上报链表)
 * \p_st_session_private                 (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC:成功\n
 *         APM_L7_ANALYZE_TODO:数据解析未结束\n
 *         APM_L7_ANALYZE_FAIL:失败\n
 */
int corba_response_parse(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, corba_session *p_st_session_private)
{
    int i_ret = 0;
    char *p_stub_data = NULL;
    unsigned int ui_stub_len = 0, ui_stub_len_tmp = 0;
    L7session_corba_private *p_st_private = NULL;
    char *p_out = NULL;

    if(p_st_data == NULL || p_st_body_data == NULL
        || p_st_session_private == NULL || p_st_session_private->p_st_private == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = p_st_session_private->p_st_private;

    i_ret = corba_giop_header_parse(p_st_data, p_st_body_data, p_st_private);
    if(i_ret == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

    if((unsigned int)p_st_private->i_data_len > p_st_data->ui_remaining)
        return APM_L7_ANALYZE_TODO;

    switch (p_st_private->i_message_type)
    {
        case 0:
            switch (p_st_private->i_version)
            {
                case 0:
                    i_ret = giop_data_v0(p_st_data, p_st_body_data, p_st_session_private);
                    break;

                case 1:
                    i_ret = giop_data_v1(p_st_data, p_st_body_data, p_st_session_private);
                    break;

                case 2:
                    i_ret = giop_data_v2(p_st_data, p_st_body_data, p_st_session_private);
                    break;

                default:
                    return APM_L7_ANALYZE_FAIL;
            }

            if(i_ret == FR_FAIL)
                return APM_L7_ANALYZE_FAIL;

            break;

        case 1:
            switch (p_st_private->i_version)
            {
                case 0:
                case 1:
                    i_ret = giop_reply_v0(p_st_data, p_st_body_data, p_st_private);
                    if(i_ret == FR_FAIL)
                        return APM_L7_ANALYZE_FAIL;

                    break;

                case 2:
                    i_ret = giop_reply_v2(p_st_data, p_st_body_data, p_st_private);
                    if(i_ret == FR_FAIL)
                        return  APM_L7_ANALYZE_FAIL;

                    break;

                default:
                    return APM_L7_ANALYZE_FAIL;
            }

            if(i_ret == FR_FAIL)
                return APM_L7_ANALYZE_FAIL;

            break;


        default:
            if((unsigned int)p_st_private->i_data_len > p_st_data->ui_remaining)
                return APM_L7_ANALYZE_TODO;

            i_ret = bytebuff_skip (p_st_data, p_st_private->i_data_len);
            return i_ret == FR_SUCC ? APM_L7_ANALYZE_SUCC : APM_L7_ANALYZE_FAIL;
    }

    if (p_st_session_private->i_flag_weblogic)
    {
        i_ret = weblogic_stub_data_parse_resp(p_st_session_private, p_st_data, p_st_body_data);
        if (i_ret == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
    }

    if (p_st_session_private->is_was_ejb)
    {
        i_ret = was_ejb_parse_resp(p_st_session_private, p_st_data, p_st_body_data);
        if (i_ret == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
    }

    //stub data
    if(p_st_data->ui_remaining)
    {
        p_stub_data = (char *)frmalloc(p_st_data->ui_remaining);
        if(p_stub_data == NULL)
            return APM_L7_ANALYZE_FAIL;

        ui_stub_len = p_st_data->ui_remaining;

        i_ret = bytebuff_get_bytes(p_st_data, p_stub_data, p_st_data->ui_remaining);
        if(i_ret == FR_FAIL)
        {
            frfree(p_stub_data);
            return APM_L7_ANALYZE_FAIL;
        }

        //GBK--> UTF8
        i_ret = iconv_to_utf8(p_stub_data, ui_stub_len, "gb18030", &p_out, &ui_stub_len_tmp);
        if(i_ret != 0)
        {
            if(p_out)
                frfree(p_out);
        }
        else
        {
            frfree(p_stub_data);
            p_stub_data = p_out;
            ui_stub_len = ui_stub_len_tmp;
        }

        i_ret = frreport_body_l7_add_bin(p_st_body_data, "response.rpc.return", p_stub_data, ui_stub_len);
        frfree(p_stub_data);
        if(i_ret == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
    }

    return APM_L7_ANALYZE_SUCC;

}

/*!
 * 跳过utf
 *
 * \param *p_st_data           (Frbyte_Packet         数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
int skip_utf(Frbyte_Packet *p_st_data)
{
    uint32_t u32_len = 0;

    if (p_st_data == NULL)
        return FR_FAIL;

    if (bytebuff_peek_int(p_st_data, 4, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    if (u32_len != 0)
        bytebuff_skip(p_st_data, u32_len+4);

    return FR_SUCC;
}



FR_STATIC int __giop_get_private(Frlist_header *p_st_header, int i_request_id, L7session_corba_private **pp_st_private)
{
    L7session_corba_private *p_st_private = NULL;
    Frlist_node *p_st_node = NULL;

    if(p_st_header == NULL || pp_st_private == NULL)
        return FR_FAIL;

    p_st_node = FRLIST_FIRST_NODE(p_st_header);
    if(p_st_node == NULL)
        return FR_SUCC;

    while (p_st_node && p_st_node->data)
    {
        p_st_private = (L7session_corba_private *)p_st_node->data;

        if(p_st_private->i_request_id == i_request_id)
        {
            frlist_node_apart(p_st_header, p_st_node);
            frfree(p_st_node);
            *pp_st_private = p_st_private;
            return FR_SUCC;
        }

        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    return FR_SUCC;

}


int giop_get_private(Frbyte_Packet *p_packet, corba_session *p_session_private)
{
    unsigned int ui_version = 0;
    int i_ret = 0, i_skip_len = 0;
    int is_little_endian = 0, i_seq_len = 0;
    unsigned int ui_seq_size = 0;
    int i_request_id;

    if(p_packet == NULL || p_session_private == NULL)
        return FR_FAIL;

    //todo
    //version
    i_ret = bytebuff_skip(p_packet, 5);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_get_int(p_packet, 1, &ui_version, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //little endian
    i_ret = bytebuff_get_int(p_packet, 1, (uint32_t *)&is_little_endian, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    is_little_endian = is_little_endian & 0x01;
    //type
    i_ret = bytebuff_skip(p_packet, 1);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //len
    i_ret = bytebuff_skip(p_packet, 4);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(ui_version == 0)
    {
        if(is_little_endian)
            i_ret = bytebuff_get_int(p_packet, 4, &ui_seq_size, BYTE_LITTLE_ENDIAN);
        else
            i_ret = bytebuff_get_int(p_packet, 4, &ui_seq_size, BYTE_BIG_ENDIAN);

        while (ui_seq_size)
        {
            i_ret = bytebuff_skip(p_packet, 4);
            if (i_ret == FR_FAIL)
                return FR_FAIL;

            if(is_little_endian)
                i_ret = bytebuff_get_int(p_packet, 4,(uint32_t *) &i_seq_len, BYTE_LITTLE_ENDIAN);
            else
                i_ret = bytebuff_get_int(p_packet, 4, (uint32_t *) &i_seq_len, BYTE_BIG_ENDIAN);

            if (i_ret == FR_FAIL)
                return FR_FAIL;

            i_ret = bytebuff_skip(p_packet, i_seq_len);
            if (i_ret == FR_FAIL)
                return FR_FAIL;

            if (p_packet->ui_remaining)
            {
                i_skip_len = i_seq_len % 4;
                if (i_skip_len)
                {
                    i_skip_len = 4 - i_skip_len;
                }

                i_ret = bytebuff_skip(p_packet, i_skip_len);
                if(i_ret == FR_FAIL)
                    return FR_FAIL;
            }

            ui_seq_size--;
        }
    }

    if(is_little_endian)
        i_ret = bytebuff_get_int(p_packet, 4,(uint32_t *) &i_request_id, BYTE_LITTLE_ENDIAN);
    else
        i_ret = bytebuff_get_int(p_packet, 4, (uint32_t *) &i_request_id, BYTE_BIG_ENDIAN);

    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //todo
    i_ret = __giop_get_private(&p_session_private->st_private, i_request_id, &p_session_private->p_st_private);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}
